package com.agenda;


import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.RawContacts.Data;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class P3_AgendaExchangeActivity extends Activity {
	
	 private Button shareButton;
	 private Button receiveButton;
	 private Button exitButton;
	 
	 private BluetoothService mService = null;
	 
	 private Intent mainActivityIntent;
	 
	 private final int TIMEOUT = 30000; // 30 seconds will be the timeout for showing the QR code to the client before the operation is cancelled.
	 
	 private BluetoothAdapter mBluetoothAdapter = null; 	 // Local Bluetooth adapter.
	 
	 //request codes for onActivityResult
	 private static final int REQUEST_ENABLE_BT = 0;
	 private static final int PICK_CONTACT_REQUEST=1;	
	 private static final int READING_QR = 2; 

	 private String MAC;
	 
	// Message types sent from the BluetoothService Handler
	 public static final int MESSAGE_STATE_CHANGE = 0;
	 public static final int MESSAGE_READ = 1;
	 public static final int MESSAGE_WRITE = 2;	
	 public static final int MESSAGE_TOAST = 3;
	 public static final int MESSAGE_TIMEOUT = 4;
	    
	 // Key names received from the BluetoothService Handler
	 public static final String TOAST = "toast";    
	 
	 public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        setContentView(R.layout.main);        
        shareButton = (Button) findViewById(R.id.share_button);
        shareButton.setOnClickListener(shareButtonListener);        
        receiveButton = (Button) findViewById(R.id.receive_button);
        receiveButton.setOnClickListener(receiveButtonListener);        
        exitButton = (Button) findViewById(R.id.exit_button);
        exitButton.setOnClickListener(exitButtonListener);       
        
        //In some situations, we'll want to go back to the main activity and remove any other activity on the top of the stack
        //(QR Code App and possibly an unwanted duplicate instance of the main activity)
        //this intent will be used in more than one situation so we set it here.
        mainActivityIntent =new Intent(getApplicationContext(),P3_AgendaExchangeActivity.class);
        mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        
        setupBluetooth();       
	 }	 

	 void setupBluetooth(){
		 
		 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();	
	     if (mBluetoothAdapter == null) {      // If the adapter is null, then Bluetooth is not supported
	    	 Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
	         finish();           
	     
	     }else if (mBluetoothAdapter.isEnabled()) {
	        MAC= mBluetoothAdapter.getAddress();   
	        
	     }else{  //if Bluetooth is not enabled, we'll ask the user to enable it
	      	Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
	        startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
	     }	 
	 }
	 
	 public void onResume() {
			super.onResume();		
	 }
		
	 public void onPause() {
			super.onPause();		
	 }
		
	 @Override
	    public void onDestroy() {
	        super.onDestroy();
	        // Make sure to stop the BluetoothService
	        // calling mService.stop() will stop any thread that is running.	  
	        if (mService != null) {
	        	mService.stop();
	        	mService = null;
	        }
	        mHandler.removeMessages(MESSAGE_TIMEOUT); //After the TIMEOUT we start the main activity again (see Handler) so if don't remove the handler msg before closing,
	        										  //the app will be launched again.
	    }
				
	 private OnClickListener shareButtonListener = new OnClickListener() {
	        public void onClick(View v) {	        		
	        	if(mService != null){  //Stop the BluetoothService if it is running
	        						   //because if the phone was sharing and will now be receiving, 
	        						   //the BluetoothService that is already running would have the wrong parameters
	        						   //so if we already have a BluetoothService, we need to close it, to be ready to start a new BluetoothService
					mService.stop();
					mService = null;
				}
	         	Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
            	startActivityForResult(intent,PICK_CONTACT_REQUEST); //let the user choose the contact he wants to share             	
	        }
	 };
	  
	 private OnClickListener receiveButtonListener = new OnClickListener() {
	        public void onClick(View v) {    
	        	if(mService != null){ 	//Stop the BluetoothService if it is running
					   					//because if the phone was receiving and will now be sharing, 
	        							//the BluetoothService that is already running would have the wrong parameters
					   					//so if we already have a BluetoothService, we need to close it, to be ready to start a new BluetoothService
					mService.stop();
					mService = null;
				}	        	
	        	receiveContact(); 	        	
	        }
	  };
    
	 private OnClickListener exitButtonListener = new OnClickListener() {
	        public void onClick(View v) {
	        	finish(); //close the application
	        }
	 }; 
	    

	 private void receiveContact(){        
	        
	    if(isIntentAvailable(this,"com.google.zxing.client.android.SCAN")){ //Before starting the intent, we check if will be possible
	    	Intent intent_readQR = new Intent("com.google.zxing.client.android.SCAN");		
	    	intent_readQR.putExtra("SCAN_MODE", "QR_CODE_MODE");
	    	startActivityForResult(intent_readQR, READING_QR); //read the QR Code (from the other phone)
	    }else //if user doesn't have the necessary BarCode app
	    	Toast.makeText(this, "First install the app 'BarCode Scanner'", Toast.LENGTH_LONG).show();
	 }
	 
	 
    private void showQRCode(){    	
    	if(isIntentAvailable(this,"com.google.zxing.client.android.SCAN")){ 
    		Intent intent_writeQR = new Intent("com.google.zxing.client.android.ENCODE");
        	intent_writeQR.putExtra("ENCODE_TYPE", "TEXT_TYPE");
        	intent_writeQR.putExtra("ENCODE_DATA", MAC); //will turn the user's MAC address into a QR Code
        	
        	Message msg = mHandler.obtainMessage(MESSAGE_TIMEOUT); //we only want to show the QRCode for some time, and then it will timeout
        													       //(unless the other phone is able to connect to it in the meantime)       	
        	mHandler.sendMessageDelayed(msg, TIMEOUT);        	   //we'll send a message to the handler after TIMEOUT milisseconds.
        	startActivity(intent_writeQR);         	
    	}else
    		Toast.makeText(this, "First install the app 'BarCode Scanner'", Toast.LENGTH_SHORT).show();
    }
    
	
  	@Override //Processing the requestCode of the activities we started with,and the additional data from it
  	public void onActivityResult(int reqCode, int resultCode, Intent intent) {
  	  super.onActivityResult(reqCode, resultCode, intent);

	  	  switch (reqCode) {
	  	  	case REQUEST_ENABLE_BT:	  	  		
		        if (resultCode == Activity.RESULT_OK) {
		            // Bluetooth is now enabled
		            MAC= mBluetoothAdapter.getAddress();     
		        } else {
		            // User did not enable Bluetooth or an error occured
		            Toast.makeText(this, "Bluetooth not enabled", Toast.LENGTH_LONG).show();
		            finish();
		        }
				
			break; 	  
	  	  	case PICK_CONTACT_REQUEST:  
	  	  		
	  	  	if (resultCode == Activity.RESULT_OK) {
	  	        Uri contactData = intent.getData();
	  	        //Read the result of Contact List using the Cursor
	  	        Cursor c =  managedQuery(contactData, null, null, null, null);
	  	        if (c.moveToFirst()) {
	  	        	//Read selected name from the contactList by phoneuser
	  	        	String name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
	  	        	String phoneNumber="";
	        	         //Read the ID 
	  	        	String contactId = c.getString(c.getColumnIndex( 
	  	             ContactsContract.Contacts._ID));
	  	        	
	  	        	String hasPhone = c.getString(c.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
	  	        //Check if phoneNumber exists
	  	        	if(hasPhone.equals("1"))
	  	        	 { 
	  	        	      // if it has a phone number, then 
	  	        	      Cursor phones = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId, null, null); 
	  	        	      phones.moveToFirst();
	  	        	      phoneNumber = phones.getString(phones.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER)); 
	  	        	 }
	  	        //Send Name and PhoneNumber to the service
	  	        	mService = new BluetoothService(this, mHandler,name,phoneNumber);   
	  	        	//Call BluetoothServerThread
	  	        	if (mService != null) {
	  	              // Only if the state is STATE_NONE, do we know that we haven't started already
	  	              if (mService.getState() == BluetoothService.STATE_NONE) {
	  	                // Start the Bluetooth services
	  	                mService.start();
	  	              }
	  	          } 
	  	        	
	  	        	showQRCode();  	      
	  	        }
  	  		}//else
  	  			//Toast.makeText(this, "Try to choose a contact again.", Toast.LENGTH_LONG).show();	
	  	  	  
	  	    break;  	 
	  	    
	  	  	case READING_QR:	  	  		
				if (resultCode == RESULT_OK) {
					String contents = intent.getStringExtra("SCAN_RESULT"); //contents is the MAC address (of the other phone) that has been read
					Toast.makeText(this, "MAC read: "+contents, Toast.LENGTH_SHORT).show();					
					
					mService = new BluetoothService(this, mHandler,null,null); //notice how when the phone is receiving, the last two parameters (name,phone) are null
					BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(contents); 
			        // Attempt to connect to the device
			        mService.connect(device);
	
				} else if (resultCode == RESULT_CANCELED) {
				    Toast.makeText(this, "Can't read the QR Code.", Toast.LENGTH_LONG).show();	               
				}
			break;
		
	  	  }
  	}  	
  	
  	//To check if an Intent with the specified action can be sent and responded.  	
  	public static boolean isIntentAvailable(Context context,String action){
  		final PackageManager packageManager =context.getPackageManager();
  		final Intent intent=new Intent(action);
  		List<ResolveInfo> list= packageManager.queryIntentActivities(intent,PackageManager.MATCH_DEFAULT_ONLY);
  		
  		return list.size() > 0;
  	} 	
  	
 // The Handler that gets information back from the BluetoothService
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_READ:
            	
            	byte[] readBuf = (byte[]) msg.obj;
                // construct a string from the valid bytes in the buffer
                //Convert Buffer to string
               String receiveData = new String(readBuf,0,msg.arg1);

               //Split string by #
               String [] nameAndPhone=receiveData.split("#");
               String name=nameAndPhone[0];
               String phonenumber=nameAndPhone[1];
               
        	   //Create Arraylist object of ContentProviderOperation
               ArrayList<ContentProviderOperation> contentOperations = new ArrayList<ContentProviderOperation>();
               int rawContactInsertIndex = contentOperations.size();
               
               //Adding data to ContentProviderOperation Arraylist
               contentOperations.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
               .withValue(RawContacts.ACCOUNT_TYPE, null)
               .withValue(RawContacts.ACCOUNT_NAME,null )
               .build());
               contentOperations.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
               .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
               .withValue(Data.MIMETYPE,Phone.CONTENT_ITEM_TYPE)
               .withValue(Phone.NUMBER, phonenumber)
               .build());
               contentOperations.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
               .withValueBackReference(Data.RAW_CONTACT_ID, rawContactInsertIndex)
               .withValue(Data.MIMETYPE,StructuredName.CONTENT_ITEM_TYPE)
               .withValue(StructuredName.DISPLAY_NAME, name)
               .build()); 
               try
               {
            	   //Perfom applyBatch operation to save the content.
               ContentProviderResult[] res = getContentResolver().applyBatch(ContactsContract.AUTHORITY, contentOperations);
               Toast.makeText(getApplicationContext(), "Contact saved successfully.",
                       Toast.LENGTH_SHORT).show();
               }catch(Exception ex)
               {
            	   Toast.makeText(getApplicationContext(), "Contact NOT saved successfully.",
                           Toast.LENGTH_SHORT).show();
               }
                
                break;
           
            case MESSAGE_WRITE: //phone that is sharing has sent some data through bluetooth
            				    //we no longer need to display the QR Code, so we just start the main activity
            	                //and finish any other activities on top of the stack (see mainActivityIntent flag in onCreate)
                startActivity(mainActivityIntent);
                mHandler.removeMessages(MESSAGE_TIMEOUT);
                Toast.makeText(getApplicationContext(), "Contact data was sent.",
                        Toast.LENGTH_SHORT).show();                
                break;

            case MESSAGE_TOAST:
                Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), //will get a message saying connection was lost or failed
                               Toast.LENGTH_SHORT).show();                
                startActivity(mainActivityIntent); //once again, we want to show the main activity (see mainActivityIntent declaration in onCreate)
                mHandler.removeMessages(MESSAGE_TIMEOUT); //we remove any TIMEOUT message because we've already closed the QR Code activity
                                                          //so we don't need to do it again.
                break;
            
            case MESSAGE_TIMEOUT:            	
                startActivity(mainActivityIntent); //once again, we want to show the main activity (see mainActivityIntent declaration in onCreate)
            	break;
            }
        }
    };
  	
}